package com.hg.library.manager;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;

import com.hispot.download.FileDownloadConstant;
import com.hispot.download.FileDownloadModel;
import com.hispot.download.FileDownloadSQLiteHelper;

/**
 * Created by admin on 2017/2/27.
 */

public class FileDownloadService extends BroadcastReceiver {
    private static final String TAG = "FileDownloadService";

    private static final String ACTION = "android.action.HiSpot.DownloadService";

    public static final String DOWNLOAD_URI = "content://com.hg.store.DOWNLOAD_INFO";

    public static final int CHECKED_INSTALL_STATE = 1;

    public static final int BINDEL_MODEL_FLAG = 1;

    private Context mContext;

    private final int wait = 1, pause = 2, download = 3, complete = 4, error = 5, installSuccess = 6, installFailed = 7;

    private final int DELETE_ACTION = 10, PAUSE_ACTION = 11, START_ACTION = 12;

    private OnFileDownloadInfoListener l;

    private OnFileDownloadCommandListener onFileDownloadCommandListener;

    public FileDownloadService(Context mContext) {
        this.mContext = mContext;
    }

    /**
     * client 端调用 接受下载状态消息
     * @param l
     */
    public void setOnFileDownloadInfoListener(OnFileDownloadInfoListener l) {
        this.l = l;
    }

    /**
     * 服务端调用 接受下载相关命令
     * @param onFileDownloadCommandListener
     */
    public void setOnFileDownloadCommandListener(OnFileDownloadCommandListener onFileDownloadCommandListener) {
        this.onFileDownloadCommandListener = onFileDownloadCommandListener;
    }

    public void attachService() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION);
        mContext.registerReceiver(this, intentFilter);
    }

    public void detachService() {
        mContext.unregisterReceiver(this);
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        if (l != null) {

            int state = intent.getIntExtra("state", 0);
            String url = intent.getStringExtra("url");
            long soFar = intent.getLongExtra("soFar", 0);
            long total = intent.getLongExtra("total", 0);
            int percent = intent.getIntExtra("percent", 0);
            String filePath = intent.getStringExtra("filePath");
            int code = intent.getIntExtra("code", -1);
            int downloadError = intent.getIntExtra("downloadError", -1);
            String errorMessage = intent.getStringExtra("errorMessage");
            String packageName = intent.getStringExtra("packageName");
            String intentUri = intent.getStringExtra("intentUri");

            switch (state) {
                case wait:
                    l.onWaiting(url, soFar, total, percent);
                    break;
                case pause:
                    l.onPause(url, soFar, total, percent);
                    break;
                case download:
                    l.onDownloading(url, soFar, total, percent);
                    break;
                case complete:
                    l.onComplete(url, filePath);
                    break;
                case error:
                    l.onError(url, code, downloadError, errorMessage);
                    break;
                case installSuccess:
                    l.onInstallSuccess(packageName, intentUri);
                    break;
                case installFailed:
                    l.onInstallFailed(packageName);
                    break;
            }
        }

        if (onFileDownloadCommandListener != null) {

            int state = intent.getIntExtra("state", 0);
            String downloadUrl = intent.getStringExtra("downloadUrl");
            String fileName = intent.getStringExtra("fileName");

            switch (state) {
                case START_ACTION:
                    onFileDownloadCommandListener.start(downloadUrl, fileName);
                    break;
                case PAUSE_ACTION:
                    onFileDownloadCommandListener.pause(downloadUrl);
                    break;
                case DELETE_ACTION:
                    onFileDownloadCommandListener.delete(downloadUrl);
                    break;
            }
        }
    }

    public static synchronized FileDownloadModel getDownloadStatus(Context context, String downloadUrl) {
        return getDownloadStatus(context, downloadUrl);
    }

    public synchronized FileDownloadModel getDownloadStatus(String downloadUrl) {
        return getDownloadStatus(mContext, DOWNLOAD_URI, downloadUrl);
    }

    private static synchronized FileDownloadModel getDownloadStatus(Context context, String uri, String downloadUrl) {
        ContentResolver resolver = context.getContentResolver();
        FileDownloadModel model = new FileDownloadModel();
        model.downloadUrl = downloadUrl;

        Cursor query = resolver.query(Uri.parse(uri), null, FileDownloadConstant.DOWNLOAD_URL + " like ?", new String[]{downloadUrl}, null);

        if (query != null && !query.isClosed() && query.moveToFirst()) {
            model.soFar = query.getLong(query.getColumnIndex(FileDownloadConstant.START_POINT));
            model.total = query.getLong(query.getColumnIndex(FileDownloadConstant.TOTAL));
            model.status = query.getInt(query.getColumnIndex(FileDownloadConstant.DOWNLOAD_STATUS));

            model.percent = (int) ((double) model.soFar / model.total * 100);

            query.close();
        }
        return model;
    }

    public void binderDownloadService(DownloadServiceConnection conn) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.hg.store", "com.hg.store.service.DownloadExportedService"));
        mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    public void unbinderDownloadService(DownloadServiceConnection conn) {
        conn.onDownloadServiceInfoListener = null;
        mContext.unbindService(conn);
    }

    public static class DownloadServiceConnection implements ServiceConnection {

        OnDownloadServiceInfoListener onDownloadServiceInfoListener;

        private Messenger messenger = new Messenger(new Handler() {
            @Override
            public void handleMessage(Message msg) {

                switch (msg.what) {

                    case FileDownloadService.CHECKED_INSTALL_STATE:
                        FileDownloadModel model = new FileDownloadModel();

                        Bundle data = msg.getData();
                        int install_state = data.getInt("install_state", -1);
                        model.status = install_state;
                        model.packageName = data.getString("packageName");

                        if (onDownloadServiceInfoListener != null) {
                            onDownloadServiceInfoListener.onResult(model);
                        }
                        break;
                }
            }
        });

        private Messenger mes;

        public DownloadServiceConnection(OnDownloadServiceInfoListener onDownloadServiceInfoListener) {
            this.onDownloadServiceInfoListener = onDownloadServiceInfoListener;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mes = new Messenger(service);
            if (onDownloadServiceInfoListener != null) {
                onDownloadServiceInfoListener.onConnected();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mes = null;
        }

        public boolean requestDownloadStatus(String packageName) {
            Message message = new Message();
            message.what = FileDownloadService.CHECKED_INSTALL_STATE;
            Bundle bundle = new Bundle();
            bundle.putString("packageName", packageName);
            message.setData(bundle);
            message.replyTo = messenger;
            return sendMessage(message);
        }

        public boolean sendMessage(Message message) {
            if (mes != null) {
                try {
                    mes.send(message);
                } catch (RemoteException e) {
                    return false;
                }
                return true;
            }
            return false;
        }
    }

    public interface OnDownloadServiceInfoListener {
        public void onResult(FileDownloadModel downloadModel);
        public void onConnected();
    }

    public void sendStartData(String url) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("url", url);
        mContext.sendBroadcast(intent);
    }

    public void sendWaitingData(String url, long soFar, long total, int percent) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", wait);
        intent.putExtra("url", url);
        intent.putExtra("soFar", soFar);
        intent.putExtra("total", total);
        intent.putExtra("percent", percent);
        mContext.sendBroadcast(intent);
    }

    public void sendPauseData(String url, long soFar, long total, int percent) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", pause);
        intent.putExtra("url", url);
        intent.putExtra("soFar", soFar);
        intent.putExtra("total", total);
        intent.putExtra("percent", percent);
        mContext.sendBroadcast(intent);
    }

    public void sendDownloadingData(String url, long soFar, long total, int percent) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", download);
        intent.putExtra("url", url);
        intent.putExtra("soFar", soFar);
        intent.putExtra("total", total);
        intent.putExtra("percent", percent);
        mContext.sendBroadcast(intent);
    }

    public void sendCompleteData(String url, String filePath) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", complete);
        intent.putExtra("url", url);
        intent.putExtra("filePath", filePath);
        mContext.sendBroadcast(intent);
    }

    public void sendErrorData(String url, int code, int downloadError, String errorMessage) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", error);
        intent.putExtra("url", url);
        intent.putExtra("code", code);
        intent.putExtra("downloadError", downloadError);
        intent.putExtra("errorMessage", errorMessage);
        mContext.sendBroadcast(intent);
    }

    public void sendInstallSuccess(String packageName, String intentUri) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", installSuccess);
        intent.putExtra("packageName", packageName);
        intent.putExtra("intentUri", intentUri);
        mContext.sendBroadcast(intent);
    }

    public void sendInstallFailed(String packageName) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", installFailed);
        intent.putExtra("packageName", packageName);
        mContext.sendBroadcast(intent);
    }

    public void start(String downloadUrl, String fileName) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", START_ACTION);
        intent.putExtra("downloadUrl", downloadUrl);
        intent.putExtra("fileName", fileName);
        mContext.sendBroadcast(intent);
    }

    public void delete(String downloadUrl) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", DELETE_ACTION);
        intent.putExtra("downloadUrl", downloadUrl);
        mContext.sendBroadcast(intent);
    }

    public void pause(String downloadUrl) {
        Intent intent = new Intent(ACTION);
        intent.putExtra("state", PAUSE_ACTION);
        intent.putExtra("downloadUrl", downloadUrl);
        mContext.sendBroadcast(intent);
    }

    public static class DownloadProvider extends ContentProvider {
        FileDownloadSQLiteHelper sqLiteHelper;

        @Override
        public boolean onCreate() {
            sqLiteHelper = new FileDownloadSQLiteHelper(getContext());
            return true;
        }

        @Nullable
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
            SQLiteDatabase readableDatabase = sqLiteHelper.getReadableDatabase();
            return readableDatabase.query(FileDownloadConstant.TABLE_NAME, projection, selection, selectionArgs, sortOrder, null, null);
        }

        @Nullable
        @Override
        public String getType(Uri uri) {
            return null;
        }

        @Nullable
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            return null;
        }

        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }

        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            return 0;
        }
    }

    public interface OnFileDownloadInfoListener {
        void onStart(String url);

        void onWaiting(String url, long soFar, long total, int percent);

        void onPause(String url, long soFar, long total, int percent);

        void onDownloading(String url, long soFar, long total, int percent);

        void onComplete(String url, String filePath);

        void onError(String url, int code, int downloadError, String errorMessage);

        void onInstallSuccess(String packageName, String intentUri);//安装成功

        void onInstallFailed(String packageName);//安装失败
    }

    public interface OnFileDownloadCommandListener {

        void delete(String url);

        void start(String url, String fileName);

        void pause(String url);
    }
}
